package org.jaaksi.customviewdemo.roundview

import android.content.Context
import android.graphics.Canvas
import android.graphics.Path
import android.util.AttributeSet
import android.view.View
import androidx.constraintlayout.widget.ConstraintLayout
import org.jaaksi.customviewdemo.R

/**
 * 不同于DJRoundConstraintLayout，这个可以裁减child，不支持Ripple等
 * @see DJRoundConstraintLayout
 */
class DJRoundClipConstraintLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : ConstraintLayout(
    context, attrs, defStyleAttr
) {
    private val path = Path()

    /**
     * 椭圆or圆形
     */
    var halfRoundCorner = false
        set(value) {
            field = value
            requestLayout()
        }
    var cornerRadius = 0f
        private set
    var topLeftRadius = 0f
        private set
    var topRightRadius = 0f
        private set
    var bottomLeftRadius = 0f
        private set
    var bottomRightRadius = 0f
        private set

    private val radiusArr = FloatArray(8)

    init {
        obtainAttributes(attrs)
    }

    private fun obtainAttributes(attrs: AttributeSet?) {
        attrs ?: return
        val attr = context.obtainStyledAttributes(attrs, R.styleable.DJRoundClipConstraintLayout)
        cornerRadius =
            attr.getDimension(R.styleable.DJRoundClipConstraintLayout_rv_radius, 0f)
        halfRoundCorner = attr.getBoolean(R.styleable.DJRoundClipConstraintLayout_rv_halfRoundCorner, false)
        topLeftRadius =
            attr.getDimension(R.styleable.DJRoundClipConstraintLayout_rv_topLeftRadius, 0f)
        topRightRadius =
            attr.getDimension(R.styleable.DJRoundClipConstraintLayout_rv_topRightRadius, 0f)
        bottomLeftRadius =
            attr.getDimension(R.styleable.DJRoundClipConstraintLayout_rv_bottomRightRadius, 0f)
        bottomRightRadius =
            attr.getDimension(R.styleable.DJRoundClipConstraintLayout_rv_bottomRightRadius, 0f)
        setRadii()
        attr.recycle()
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        super.onLayout(changed, left, top, right, bottom)
        if (halfRoundCorner) {
            setRadius(radius = height / 2f)
        }
    }

    override fun draw(canvas: Canvas) {
        canvas.blockDraw {
            super.draw(canvas)
        }
    }

    override fun drawChild(canvas: Canvas, child: View?, drawingTime: Long): Boolean {
        // 如果background为空，是不会走draw的，单独裁减drawChild的canvas
        return if (background == null) {
            canvas.blockDraw {
                super.drawChild(canvas, child, drawingTime)
            }
        } else {
            super.drawChild(canvas, child, drawingTime)
        }
    }

    private fun <T> Canvas.blockDraw(block: () -> T): T {
        val id = save()
        // 直接裁减画布
        path.reset()
        path.addRoundRect(
            0f,
            0f,
            width.toFloat(),
            height.toFloat(),
            radiusArr,
            Path.Direction.CW
        )
        clipPath(path)
        return block().apply {
            restoreToCount(id)
        }
    }

    fun setRadius(
        radius: Float = 0f,
        topLeftRadius: Float = 0f,
        topRightRadius: Float = 0f,
        bottomLeftRadius: Float = 0f,
        bottomRightRadius: Float = 0f,
    ) {
        this.cornerRadius = radius
        this.topLeftRadius = topLeftRadius
        this.topRightRadius = topRightRadius
        this.bottomLeftRadius = bottomLeftRadius
        this.bottomRightRadius = bottomRightRadius
        setRadiiAndInvalid()
    }

    private fun setRadiiAndInvalid() {
        setRadii()
        postInvalidate()
    }

    private fun setRadii() {
        if (topLeftRadius > 0 || topRightRadius > 0 || bottomRightRadius > 0 || bottomLeftRadius > 0) {
            /**The corners are ordered top-left, top-right, bottom-right, bottom-left */
            radiusArr[0] = topLeftRadius
            radiusArr[1] = topLeftRadius
            radiusArr[2] = topRightRadius
            radiusArr[3] = topRightRadius
            radiusArr[4] = bottomRightRadius
            radiusArr[5] = bottomRightRadius
            radiusArr[6] = bottomLeftRadius
            radiusArr[7] = bottomLeftRadius
        } else {
            radiusArr[0] = cornerRadius
            radiusArr[1] = cornerRadius
            radiusArr[2] = cornerRadius
            radiusArr[3] = cornerRadius
            radiusArr[4] = cornerRadius
            radiusArr[5] = cornerRadius
            radiusArr[6] = cornerRadius
            radiusArr[7] = cornerRadius
        }
    }

}